;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;//                                                                                                                            //
;//                                                         WNProject                                                          //
;//                                                                                                                            //
;//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
;//                                                                                                                            //
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.486
.MODEL FLAT, C
OPTION CASEMAP: NONE

.CODE

BeginFiber PROC, retptrloc:PTR, oldstackloc:PTR, inValue:PTR, func:PTR, stackloc:PTR, stacksize:DWORD, stackleft:DWORD
    ASSUME FS:NOTHING
    push ebp
    push ebx
    push edi
    push esi
    push fs:[4h]
    push fs:[8h]
    mov ebx, stackloc
    sub ebx, stackleft
    mov fs:[4h], ebx
    add ebx, stacksize
    mov fs:[8h], ebx
    call _DUMMY_CALL
  _DUMMY_CALL:
    mov eax, [esp]
    add eax, 37
    mov ecx, [retptrloc]
    mov [ecx], eax
    add esp, 4
    push ebp
    mov ecx, [oldstackloc]
    mov [ecx], esp
    mov eax, esp
    sub eax, 16
    mov ecx, inValue
    mov ebx, func
    mov esp, stackloc
    push ecx
    call ebx
    pop esp
    pop ebp
    pop fs:[8h]
    pop fs:[4h]
    pop esi
    pop edi
    pop ebx
    pop ebp
    mov [eax], eax
    ret
    ASSUME FS:ERROR
BeginFiber ENDP

SwitchFiber PROC, pushstacklocation:PTR, oldscriptptr:PTR, cont:DWORD, retpt:PTR, setrunnable:PTR, retloc:PTR, inValue:PTR, stacksize:DWORD, stackleft:DWORD
    ASSUME FS:NOTHING
    ; //Save off everything, who knows when we will get back onto the correct stack
    push ebp
    push ebx
    push edi
    push esi
    mov ebx, oldscriptptr
    sub ebx, stackleft
    mov fs:[4h], ebx
    add ebx, stacksize
    mov fs:[8h], ebx
    mov eax, [pushstacklocation]
    mov [eax], esp; //Store our current stack into the correct location
    mov ecx, esp
    sub ecx, 16
    call _DUMMY_CALL
  _DUMMY_CALL:
    mov eax, [esp] ;//push the old stack pointer (calling location) back onto the stack
    add eax, 33; //offset our call-back location to right after our 'ret'
    mul cont   ;//multiply eax by 1 or 0 (are we coming back or not)
    mov ebx, retloc
    mov [ebx], eax
    mov eax, setrunnable
    mov ebx, inValue
    mov edx, retpt
    mov esp, oldscriptptr
    push ebx
    mov [eax], eax
    mov eax, ecx
    call edx
    pop ebp ;//this is the "crap" base pointer from the other thread
    pop esi; //we want to get rid of the passed parameter from the stack (we wont be going back this way)
    pop esi ;//and esi, edi, ebx, and ebp
    pop edi
    pop ebx
    pop ebp ;//this is our "correct" base pointer that we will need
    mov [eax], eax
    ret
    ASSUME FS:ERROR
SwitchFiber ENDP

EndFiber PROC, pushstacklocation:PTR, oldscriptptr:PTR, cont:DWORD, retpt:PTR, setrunnable:PTR, retloc:PTR
    ; //Save off everything, who knows when we will get back onto the correct stack
    push ebp
    push ebx
    push edi
    push esi
    mov ecx, setrunnable
    mov eax, [pushstacklocation]
    mov [eax], esp          ; Store our current stack into the correct location
    call _DUMMY_CALL
  _DUMMY_CALL:
    mov eax, [esp]          ; Push the old stack pointer (calling location) back onto the stack
    push oldscriptptr 
    push retpt              ; Push our return location onto the stack ('ret' will go here)
    add eax, 23             ; Offset our call-back location to right after our 'ret'
    mul cont                ; Multiply eax by 1 or 0 (are we coming back or not)
    mov ebx, retloc
    mov [ebx], eax
    mov eax, ecx
    retn
    pop ebp                 ; This is the "crap" base pointer from the other thread
    pop esi                 ; We want to get rid of the passed parameter from the stack (we wont be going back this way)
    pop esi                 ; and esi, edi, ebx, and ebp
    pop edi
    pop ebx
    pop ebp                 ; This is our "correct" base pointer that we will need
    mov [eax], eax
    ret
EndFiber ENDP

END